﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace IdeaNMR.Web.Core
{
    public class Draft
    {
        public static void Delete(Guid id, string userName)
        {
            if (id == Guid.Empty) throw new ArgumentException("The Id of the draft to be deleted is empty.");
            if (string.IsNullOrWhiteSpace(userName)) throw new ArgumentException("The username of the user whose draft to be deleted is null or empty.");

            IdeaNMRdbContainer inmr = new IdeaNMRdbContainer();
            BaseObject target = (from s in inmr.BaseObjects
                                 where s.Id == id && s.IsDraft
                                 select s).FirstOrDefault();

            if (target == null)
            {
                string err = string.Format("The draft with Id {{{0}}} not found.", id);
                throw new InvalidOperationException(err);
            }

            bool isAuthor = false;
            EntityType eT = target.GetEntityType();

            switch (eT)
            {
                case EntityType.Spectrometer:
                    {
                        Spectrometer spec = (Spectrometer)target;
                        if (!spec.UserReference.IsLoaded) spec.UserReference.Load();
                        isAuthor = spec.User.Username == userName;
                    }
                    break;
                case EntityType.Sample:
                    {
                        Sample samp = (Sample)target;
                        if (!samp.UserReference.IsLoaded) samp.UserReference.Load();
                        isAuthor = samp.User.Username == userName;
                    }
                    break;
                case EntityType.PulseProgram:
                case EntityType.WaveShape:
                case EntityType.Cpd:
                case EntityType.Script:
                    {
                        NMRObject o = (NMRObject)target;
                        if (!o.Authors.IsLoaded) o.Authors.Load();
                        isAuthor = o.Authors.Any(aa =>
                            {
                                if (!aa.UserReference.IsLoaded) aa.UserReference.Load();
                                return aa.User.Username == userName && aa.Index < 0;
                            });
                    }
                    break;
            }

            if (!isAuthor) throw new UnauthorizedAccessException(string.Format("User {0} tried to remove draft with Id {{{1}}}.", userName, id));

            /// Remove all Numbered authors
            if (target is NMRObject)
            {
                NMRObject nmo = (NMRObject)target;
                NumberedAuthor[] aas = nmo.Authors.ToArray();
                nmo.Authors.Clear();
                foreach (NumberedAuthor a in aas)
                    inmr.DeleteObject(a);
            }

            if (target is AuxComponent)
            {
                AuxComponent set = target as AuxComponent;

                // Remove all Named Components
                if (!set.NamedComponents.IsLoaded) set.NamedComponents.Load();
                NamedComponent[] comps = set.NamedComponents.ToArray<NamedComponent>();
                set.NamedComponents.Clear();
                foreach (NamedComponent nC in comps)
                    inmr.DeleteObject(nC);
            }
            
            if (target is PulseProgram)
            {
                PulseProgram pP = target as PulseProgram;

                // Remove all Named Components
                if (!pP.AuxComponents.IsLoaded) pP.AuxComponents.Load();
                NamedComponent[] comps = pP.AuxComponents.ToArray<NamedComponent>();
                pP.AuxComponents.Clear();
                foreach (NamedComponent nC in comps)
                    inmr.DeleteObject(nC);

                // Remove all experiments
                if (!pP.Experiments.IsLoaded) pP.Experiments.Load();
                var exps = pP.Experiments.ToArray();
                pP.Experiments.Clear();
                foreach (var ex in exps)
                    inmr.DeleteObject(ex);
            }

            inmr.DeleteObject(target);

            inmr.SaveChanges();
        }
    }
}
